// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.patent.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.PatentGoodsDao;
import com.liuxinlong.modules.dao.PatentGoodsRelationDao;
import com.liuxinlong.modules.entity.PatentGoods;
import com.liuxinlong.modules.entity.PatentGoodsRelation;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.patent.dto.ImportPatentGoodsDto;
import com.liuxinlong.modules.patent.service.PatentGoodsService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 专利产品信息实现类
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2023-11-23
 */
@Service
@Slf4j
public class PatentGoodsServiceImpl implements PatentGoodsService {
    @Autowired
    private PatentGoodsDao patentGoodsDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private PatentGoodsRelationDao patentGoodsRelationDao;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Override
    public List<Map<String, Object>> pageGoodsInfo(Map<String, Object> queryParam) {
        List<PatentGoods> originList = patentGoodsDao.pageGoodsList(queryParam);
        return completeResult(originList, (int) queryParam.get("startNum"));
    }

    @Override
    public int countGoods(Map<String, Object> queryParam) {
        return patentGoodsDao.getGoodsCount(queryParam);
    }

    @Override
    @Transactional
    public void addGoodsInfo(PatentGoods patentGoods, String patentSn, String softwareWork) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        String id = SnowFlake.nextIdStr();
        patentGoods.setId(id);
        if (!ObjectUtils.isEmpty(patentGoodsDao.getGoodsByProductModel(patentGoods.getProductModel()))) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同产品型号！");
        }
        List<PatentGoodsRelation> relationList = new ArrayList<>();
        if (!StringUtils.isEmpty(patentSn)) {
            List<String> patantSnList = Arrays.asList(patentSn.split(","));
            List<PatentGoodsRelation> patentList = new ArrayList<>(patantSnList.size());
            int sort = 1;
            for (String sn : patantSnList) {
                PatentGoodsRelation relation = buildRelation(id, sn, sort, 1);
                patentList.add(relation);
                sort++;
            }
            relationList.addAll(patentList);
        }
        if (!StringUtils.isEmpty(softwareWork)) {
            List<String> softwareWorkList = Arrays.asList(softwareWork.split(","));
            List<PatentGoodsRelation> softwareList = new ArrayList<>(softwareWorkList.size());
            int sort = 1;
            for (String software : softwareWorkList) {
                PatentGoodsRelation relation = buildRelation(id, software, sort, 2);
                softwareList.add(relation);
                sort++;
            }
            relationList.addAll(softwareList);
        }
        if (relationList.size() > 0) {
            patentGoodsRelationDao.insertBatch(relationList);
        }
        patentGoods.setCreateTime(currentTime);
        patentGoods.setCreateUser(currentUser.getId());
        patentGoodsDao.insert(patentGoods);
    }

    @Override
    @Transactional
    public void updateGoodsInfo(PatentGoods patentGoods, String patentSn, String softwareWork) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        PatentGoods oldInfo = patentGoodsDao.getGoodsByProductModel(patentGoods.getProductModel());
        if (!ObjectUtils.isEmpty(oldInfo) && !StringUtils.equals(oldInfo.getId(), patentGoods.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同产品型号！");
        }
        patentGoods.setCreateUser(oldInfo.getCreateUser());
        patentGoods.setCreateTime(oldInfo.getCreateTime());
        String id = patentGoods.getId();
        List<PatentGoodsRelation> relationList = new ArrayList<>();
        if (!StringUtils.isEmpty(patentSn)) {
            List<String> patantSnList = Arrays.asList(patentSn.split(","));
            List<PatentGoodsRelation> patentList = new ArrayList<>(patantSnList.size());
            int sort = 1;
            for (String sn : patantSnList) {
                PatentGoodsRelation relation = buildRelation(id, sn, sort, 1);
                patentList.add(relation);
                sort++;
            }
            relationList.addAll(patentList);
        }
        if (!StringUtils.isEmpty(softwareWork)) {
            List<String> softwareWorkList = Arrays.asList(softwareWork.split(","));
            List<PatentGoodsRelation> softwareList = new ArrayList<>(softwareWorkList.size());
            int sort = 1;
            for (String software : softwareWorkList) {
                PatentGoodsRelation relation = buildRelation(id, software, sort, 2);
                softwareList.add(relation);
                sort++;
            }
            relationList.addAll(softwareList);
        }
        patentGoodsRelationDao.deleteByProduct(id);
        if (relationList.size() > 0) {
            patentGoodsRelationDao.insertBatch(relationList);
        }
        patentGoods.setUpdateTime(currentTime);
        patentGoods.setUpdateUser(currentUser.getId());
        patentGoodsDao.updateById(patentGoods);
    }

    @Override
    @Transactional
    public void deleteGoodsInfo(String id) {
        patentGoodsDao.deleteById(id);
        patentGoodsRelationDao.deleteByProduct(id);
    }

    @Override
    public ImportResp importGoods(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
//                PatentGoods patentGoods = covertToBean(record);
                return false;
//				try {
//					UserGoodsDao.addDetail(UserGoods);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetMessage("导入专利产品数据部分失败，总数=" + resp.getTotal() + ",失败总数=" + resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入专利产品数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap<>();
                    item.put("sort", sort);
                    item.put("productClass", failRecord[0]);
                    item.put("productModel", failRecord[1]);
                    item.put("remark", failRecord[2]);
                    item.put("region", failRecord[3]);
                    item.put("patentOne", failRecord[4]);
                    item.put("patentTwo", failRecord[5]);
                    item.put("patentThree", failRecord[6]);
                    item.put("patentFour", failRecord[7]);
                    item.put("patentFive", failRecord[8]);
                    item.put("patentSix", failRecord[9]);
                    item.put("patentSeven", failRecord[10]);
                    item.put("patentEight", failRecord[11]);
                    item.put("patentNine", failRecord[12]);
                    item.put("patentTen", failRecord[13]);
                    item.put("softwareOne", failRecord[14]);
                    item.put("softwareTwo", failRecord[15]);
                    item.put("softwareThree", failRecord[16]);
                    item.put("softwareFour", failRecord[17]);
                    item.put("softwareFive", failRecord[18]);

                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    @Transactional
    public ImportResp batchAddGoods(List<ImportPatentGoodsDto> dataList) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        List<Map> failedList = new ArrayList<>();
        List<PatentGoods> importList = new ArrayList<>();
        List<PatentGoodsRelation> relationList = new ArrayList<>();
        Map<String, Map<String, String>> pDepartmentMap = patentDepartmentDao.getDepartmentMapBySn();
        Map<String,Map<String,String>> oldModelMap = patentGoodsDao.getGoodsMapByModel();
        int sort = 1;
        for (ImportPatentGoodsDto importDto : dataList) {
            PatentGoods goodsInfo = new PatentGoods();
            String id = SnowFlake.nextIdStr();
            goodsInfo.setId(id);
            if (StringUtils.isEmpty(importDto.getProductClass()) || !pDepartmentMap.containsKey(importDto.getProductClass())) {
                Map item = ObjectUtils.object2Map(importDto);
                item.put("sort", sort);
                item.put("message", "产品品类为空或产品品类不存在！");
                failedList.add(item);
                sort++;
                continue;
            }
            goodsInfo.setProductClass(pDepartmentMap.get(importDto.getProductClass()).get("id"));
            if (StringUtils.isEmpty(importDto.getProductModel()) || oldModelMap.containsKey(importDto.getProductModel().trim())) {
                Map item = ObjectUtils.object2Map(importDto);
                item.put("sort", sort);
                item.put("message", "产品型号为空或产品型号已存在！");
                failedList.add(item);
                sort++;
                continue;
            }
            goodsInfo.setProductModel(importDto.getProductModel());
            goodsInfo.setRemark(importDto.getRemark());
            goodsInfo.setRegion(importDto.getRegion());
            goodsInfo.setCreateUser(currentUser.getId());
            goodsInfo.setCreateTime(currentTime);
            importList.add(goodsInfo);
            if (!StringUtils.isEmpty(importDto.getPatentOne()) && !StringUtils.equals(importDto.getPatentOne(), "无专利")) {
                PatentGoodsRelation relationOne = buildRelation(id, importDto.getPatentOne(), 1, 1);
                relationList.add(relationOne);
                if (!StringUtils.isEmpty(importDto.getPatentTwo())) {
                    PatentGoodsRelation relationTwo = buildRelation(id, importDto.getPatentTwo(), 2, 1);
                    relationList.add(relationTwo);
                }
                if (!StringUtils.isEmpty(importDto.getPatentThree())) {
                    PatentGoodsRelation relationThree = buildRelation(id, importDto.getPatentThree(), 3, 1);
                    relationList.add(relationThree);
                }
                if (!StringUtils.isEmpty(importDto.getPatentFour())) {
                    PatentGoodsRelation relationFour = buildRelation(id, importDto.getPatentFour(), 4, 1);
                    relationList.add(relationFour);
                }
                if (!StringUtils.isEmpty(importDto.getPatentFive())) {
                    PatentGoodsRelation relationFive = buildRelation(id, importDto.getPatentFive(), 5, 1);
                    relationList.add(relationFive);
                }
                if (!StringUtils.isEmpty(importDto.getPatentSix())) {
                    PatentGoodsRelation relationSix = buildRelation(id, importDto.getPatentSix(), 6, 1);
                    relationList.add(relationSix);
                }
                if (!StringUtils.isEmpty(importDto.getPatentSeven())) {
                    PatentGoodsRelation relationSeven = buildRelation(id, importDto.getPatentSeven(), 7, 1);
                    relationList.add(relationSeven);
                }
                if (!StringUtils.isEmpty(importDto.getPatentEight())) {
                    PatentGoodsRelation relationEight = buildRelation(id, importDto.getPatentEight(), 8, 1);
                    relationList.add(relationEight);
                }
                if (!StringUtils.isEmpty(importDto.getPatentNine())) {
                    PatentGoodsRelation relationNine = buildRelation(id, importDto.getPatentNine(), 9, 1);
                    relationList.add(relationNine);
                }
                if (!StringUtils.isEmpty(importDto.getPatentTen())) {
                    PatentGoodsRelation relationTen = buildRelation(id, importDto.getPatentTen(), 10, 1);
                    relationList.add(relationTen);
                }
            }
            if (!StringUtils.isEmpty(importDto.getSoftwareOne()) && !StringUtils.equals(importDto.getSoftwareOne(), "无")) {
                PatentGoodsRelation relationOne = buildRelation(id, importDto.getSoftwareOne(), 1, 2);
                relationList.add(relationOne);
                if (!StringUtils.isEmpty(importDto.getSoftwareTwo())) {
                    PatentGoodsRelation relationTwo = buildRelation(id, importDto.getSoftwareTwo(), 2, 2);
                    relationList.add(relationTwo);
                }
                if (!StringUtils.isEmpty(importDto.getSoftwareThree())) {
                    PatentGoodsRelation relationThree = buildRelation(id, importDto.getSoftwareThree(), 3, 2);
                    relationList.add(relationThree);
                }
                if (!StringUtils.isEmpty(importDto.getSoftwareFour())) {
                    PatentGoodsRelation relationFour = buildRelation(id, importDto.getSoftwareFour(), 4, 2);
                    relationList.add(relationFour);
                }
                if (!StringUtils.isEmpty(importDto.getSoftwareFive())) {
                    PatentGoodsRelation relationFive = buildRelation(id, importDto.getSoftwareFive(), 5, 2);
                    relationList.add(relationFive);
                }
            }
        }
        if (!importList.isEmpty()) {
            patentGoodsDao.insertBatch(importList);
        }
        if (!relationList.isEmpty()) {
            patentGoodsRelationDao.insertBatch(relationList);
        }
        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() : ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setRetMessage(failedList.size() > 0 ? "导入专利产品信息成功" : "导入专利产品信息成功");
        resp.setFailedList(failedList);
        resp.setTotal(dataList.size());
        resp.setSuccessTotal(importList.size());
        resp.setFailedTotal(failedList.size());
        return resp;
    }

    @Override
    public void exportPatentGoods(Map<String, Object> queryParam, HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("专利产品信息导出excel.xlsx");
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        List<PatentGoods> patentGoodsList = patentGoodsDao.pageGoodsList(queryParam);
        Map<String,Map<String,String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Map<String, String>> relationMap = patentGoodsRelationDao.getRelationMap();
        String[] head = {"序号", "品类", "型号", "备注", "归属", "专利号1", "专利号2", "专利号3", "专利号4", "专利号5", "专利号6",
                "专利号7", "专利号8", "专利号9", "专利号10", "软著1", "软著2", "软著3", "软著4", "软著5"};
        data.setHead(head);
        String[][] dataList = new String[patentGoodsList.size()][head.length];
        int index = 0;
        for (PatentGoods item : patentGoodsList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = departmentMap.containsKey(item.getProductClass()) ? departmentMap.get(item.getProductClass()).get("sn") : "";
            dataList[index][2] = item.getProductModel();
            dataList[index][3] = item.getRemark();
            dataList[index][4] = item.getRegion();
            dataList[index][5] = relationMap.containsKey(item.getId() + "_1_1") ? relationMap.get(item.getId() + "_1_1").get("patent_info") : "";
            dataList[index][6] = relationMap.containsKey(item.getId() + "_1_2") ? relationMap.get(item.getId() + "_1_2").get("patent_info") : "";
            dataList[index][7] = relationMap.containsKey(item.getId() + "_1_3") ? relationMap.get(item.getId() + "_1_3").get("patent_info") : "";
            dataList[index][8] = relationMap.containsKey(item.getId() + "_1_4") ? relationMap.get(item.getId() + "_1_4").get("patent_info") : "";
            dataList[index][9] = relationMap.containsKey(item.getId() + "_1_5") ? relationMap.get(item.getId() + "_1_5").get("patent_info") : "";
            dataList[index][10] = relationMap.containsKey(item.getId() + "_1_6") ? relationMap.get(item.getId() + "_1_6").get("patent_info") : "";
            dataList[index][11] = relationMap.containsKey(item.getId() + "_1_7") ? relationMap.get(item.getId() + "_1_7").get("patent_info") : "";
            dataList[index][12] = relationMap.containsKey(item.getId() + "_1_8") ? relationMap.get(item.getId() + "_1_8").get("patent_info") : "";
            dataList[index][13] = relationMap.containsKey(item.getId() + "_1_9") ? relationMap.get(item.getId() + "_1_9").get("patent_info") : "";
            dataList[index][14] = relationMap.containsKey(item.getId() + "_1_10") ? relationMap.get(item.getId() + "_1_10").get("patent_info") : "";
            dataList[index][15] = relationMap.containsKey(item.getId() + "_2_1") ? relationMap.get(item.getId() + "_2_1").get("patent_info") : "";
            dataList[index][16] = relationMap.containsKey(item.getId() + "_2_2") ? relationMap.get(item.getId() + "_2_2").get("patent_info") : "";
            dataList[index][17] = relationMap.containsKey(item.getId() + "_2_3") ? relationMap.get(item.getId() + "_2_3").get("patent_info") : "";
            dataList[index][18] = relationMap.containsKey(item.getId() + "_2_4") ? relationMap.get(item.getId() + "_2_4").get("patent_info") : "";
            dataList[index][19] = relationMap.containsKey(item.getId() + "_2_5") ? relationMap.get(item.getId() + "_2_5").get("patent_info") : "";
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始值
     * @return 补全后数据
     */
    private List<Map<String, Object>> completeResult(List<PatentGoods> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        Map<String, Map<String, String>> pDepartmentMap = patentDepartmentDao.getDepartmentMap();
        int sort = startNum + 1;
        for (PatentGoods goods : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(goods);
            map.put("sort", sort);
            map.put("className", pDepartmentMap.containsKey(goods.getProductClass()) ? pDepartmentMap.get(goods.getProductClass()).get("name") : "-");
            List<PatentGoodsRelation> relationList = patentGoodsRelationDao.pageGoodsRelationList(goods.getId());
            if (relationList.size() > 0) {
                List<String> patentList = new ArrayList<>();
                List<String> softwareList = new ArrayList<>();
                for (PatentGoodsRelation relation : relationList) {
                    if (relation.getBusinessType() == 1) {
                        patentList.add(relation.getPatentInfo());
                        continue;
                    }
                    softwareList.add(relation.getPatentInfo());
                }
                map.put("patentSn", StringUtils.strip(patentList.toString(), "[]"));
                map.put("softwareWork", StringUtils.strip(softwareList.toString(), "[]"));
            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[0].trim())) {
            addRowError("产品品类不能为空", rowErrors);
        } else {
            if (record[0].trim().length() > 50) {
                addRowError("产品品类长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("产品型号不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 20) {
                addRowError("产品型号长度不能超过20", rowErrors);
            }
        }
        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 构建专利产品关联信息
     *
     * @param productId    产品id
     * @param patentInfo   专利信息
     * @param sort         排序
     * @param businessType 类型
     * @return 专利产品关联信息
     */
    private PatentGoodsRelation buildRelation(String productId, String patentInfo, int sort, int businessType) {
        PatentGoodsRelation relation = new PatentGoodsRelation();
        relation.setId(SnowFlake.nextIdStr());
        relation.setBusinessType(businessType);
        relation.setProductId(productId);
        relation.setSortNum(sort);
        relation.setPatentInfo(patentInfo);
        return relation;
    }
}
